using System;
using System.Collections.Generic;
using System.Text;

namespace ChEngine
{
	partial class BitBoardDriver
	{
        static ulong[,,] ZobristKeyGen = new ulong[6,2,64];
        const ulong CastleBlackRandom = 0x86726af5ec1ea6fdUL;
        const ulong CastleWhiteRandom = 0x02a263f7e51ea66dUL;
        const ulong LongCastleBlackRandom = 0x80ee6569eba4a6fdUL;
        const ulong LongCastleWhiteRandom = 0x91116ef5cb1ea247UL;
        const ulong BlackRandom = 0x8e56a1468ab34112UL;
        static void BuildZobristKeyGen()
        {
            Dictionary<ulong, bool> generated = new Dictionary<ulong,bool>();
            //Random rnd = new Random();
            for (int i = 0; i < 6; ++i)
            {
                for (int j = 0; j < 2; ++j)
                {
                    for (int k = 0; k < 64; ++k)
                    {
                        ulong n = 0;
                        do
                        {
                            //n = (ulong)(uint)rnd.Next() | ((ulong)(uint)rnd.Next()) << 32;
                            n = Rand.Random64();
                        }
                        while (generated.ContainsKey(n));
                        generated[n] = true;
                        ZobristKeyGen[i, j, k] = n;
                    }
                }
            }
        }
        ulong zKey;
        public ulong ZKey
        {
            get {  return zKey; }
        }
        public void CalcZobristKey(Side sideToMove)
        {
            zKey = ZobristKey(sideToMove);
        }
        public ulong ZobristKey(Side c)
        {
            ulong key = 0;
            ulong p = 1UL;
            for (int i = 0; i < 64; ++i, p <<= 1)
            {
                //White
                if (0 != (p & GetBishops(Side.White)))
                {
                    key ^= ZobristKeyGen[2, 0, i];
                }
                if (0 != (p & GetKnights(Side.White)))
                {
                    key ^= ZobristKeyGen[1, 0, i];
                }
                if (0 != (p & GetRooks(Side.White)))
                {
                    key ^= ZobristKeyGen[3, 0, i];
                }
                if (0 != (p & GetQueen(Side.White)))
                {
                    key ^= ZobristKeyGen[4, 0, i];
                }
                if (0 != (p & GetKing(Side.White)))
                {
                    key ^= ZobristKeyGen[5, 0, i];
                }
                if (0 != (p & GetPawns(Side.White)))
                {
                    key ^= ZobristKeyGen[0, 0, i];
                }
                //black
                if (0 != (p & GetBishops(Side.Black)))
                {
                    key ^= ZobristKeyGen[2, 1, i];
                }
                if (0 != (p & GetKnights(Side.Black)))
                {
                    key ^= ZobristKeyGen[1, 1, i];
                }
                if (0 != (p & GetRooks(Side.Black)))
                {
                    key ^= ZobristKeyGen[3, 1, i];
                }
                if (0 != (p & GetQueen(Side.Black)))
                {
                    key ^= ZobristKeyGen[4, 1, i];
                }
                if (0 != (p & GetKing(Side.Black)))
                {
                    key ^= ZobristKeyGen[5, 1, i];
                }
                if (0 != (p & GetPawns(Side.Black)))
                {
                    key ^= ZobristKeyGen[0, 1, i];
                }
            }
            if (whiteCanCastle)
                key ^= CastleWhiteRandom;
            if (whiteCanCastleLong)
                key ^= LongCastleWhiteRandom;
            if (blackCanCastle)
                key ^= CastleBlackRandom;
            if (blackCanCastleLong)
                key ^= LongCastleBlackRandom;
            if (c == Side.Black)
                key ^= BlackRandom;
            return key;
        }
    }
}
